package com.wkbb.sports.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wkbb.common.base.BaseServiceImpl;
import com.wkbb.common.dto.ResultDTO;
import com.wkbb.common.dto.basic.ClassInfoDto;
import com.wkbb.common.dto.basic.GradeDto;
import com.wkbb.common.dto.basic.StudentInfoDto;
import com.wkbb.common.enums.RoleTypeEnum;
import com.wkbb.common.enums.SexTypeEnum;
import com.wkbb.sports.dto.*;
import com.wkbb.sports.enums.SportsExamineTypeEnum;
import com.wkbb.sports.enums.SportsProjectTypeEnum;
import com.wkbb.sports.feign.BasicFeignService;
import com.wkbb.sports.mapper.*;
import com.wkbb.sports.model.*;
import com.wkbb.sports.service.AchievementService;
import com.wkbb.sports.utils.SportsUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

@Service
@Slf4j
public class AchievementServiceImpl extends BaseServiceImpl implements AchievementService {

    @Autowired
    private HlifeAchievementMapper hlifeAchievementMapper;

    @Autowired
    private HlifeExamineMapper hlifeExamineMapper;

    @Autowired
    private HlifeExamineRuleMapper hlifeExamineRuleMapper;

    @Autowired
    private HlifeExamineRuleItemMapper hlifeExamineRuleItemMapper;

    @Autowired
    private HlifeExamineRulePlusesMapper hlifeExamineRulePlusesMapper;

    @Autowired
    private HlifePhysicalMapper hlifePhysicalMapper;

    @Autowired
    private HlifePhysicalRuleMapper hlifePhysicalRuleMapper;

    @Autowired
    private HlifePhysicalRuleItemMapper hlifePhysicalRuleItemMapper;

    @Autowired
    private HlifePhysicalRulePlusesMapper hlifePhysicalRulePlusesMapper;

    @Autowired
    private HlifeUserMapper hlifeUserMapper;

    @Autowired
    private HlifeAchievementRecordMapper hlifeAchievementRecordMapper;

    @Autowired
    private HlifeAchievementStatMapper hlifeAchievementStatMapper;

    @Autowired
    private HlifeTermMapper hlifeTermMapper;

    @Autowired
    private BasicFeignService basicFeignService;

    public void setMapper(HlifeExamineMapper mapper) {
        super.setMapper(mapper);
    }

    /**
     * 查询学生成绩分页列表
     * */
    @Override
    public AchievementPageDto getAchievementPageList(Integer type, Long orgId, Long termId, Long gradeId, Long classId, Integer sex, Integer pageNo, Integer pageSize)
    {

        if (pageNo == null || pageSize == null)
        {
            return null;
        }

        AchievementPageDto achievementPageDto = new AchievementPageDto();

        //查询项目
        List<AchievementProjectDto> projectList = this.getProjectList(orgId,termId,gradeId,sex);

        //组装表头
        List<AchievementProjectItemDto> headerList = this.getAchievementHeader(projectList);
        achievementPageDto.setHeaderList(headerList);

        //组装成绩数据
        PageInfo<AchievementDto> pageInfo = this.getAchievementPageInfo(orgId, termId, gradeId, classId, sex, pageNo, pageSize, projectList);
        achievementPageDto.setPageInfo(pageInfo);

        return achievementPageDto;
    }

    private PageInfo<AchievementDto> getAchievementPageInfo(Long orgId, Long termId, Long gradeId, Long classId, Integer sex, Integer pageNo, Integer pageSize, List<AchievementProjectDto> projectList) {
        //查询用户
        Map<String, Object> userParams = new HashMap<String, Object>();
        userParams.put("orgId", orgId);
        userParams.put("gradeId", gradeId);
        userParams.put("classId", classId);
        userParams.put("termId", termId);
        if(null!=sex && sex!=0)
        {
            userParams.put("sex", sex);
        }

        //组装页面成绩数据
        Map<String, Object> achievementParams = null;
        Page<AchievementDto> page = PageHelper.startPage(pageNo, pageSize,true);
        PageInfo<AchievementDto> pageInfo = new PageInfo<>(hlifeAchievementMapper.getAchievementUserList(userParams));
        pageInfo.setTotal(page.getTotal());
        if(page.getTotal()>0){
            for(AchievementDto achievementDto : pageInfo.getList()){

                achievementDto.setTermId(termId);
                achievementDto.setStrSex(this.getSexName(achievementDto.getSex().intValue()));

                //根据项目查询学生成绩
                List<AchievementProjectItemDto> achievementList = new ArrayList<>();
                for(AchievementProjectDto achievementProjectDto : projectList)
                {
                    AchievementProjectItemDto projectItemDto = new AchievementProjectItemDto();
                    projectItemDto.setType(achievementProjectDto.getType());
                    projectItemDto.setProjectId(achievementProjectDto.getId());
                    projectItemDto.setProjectName(achievementProjectDto.getName());

                    achievementParams = new HashMap<String, Object>();
                    achievementParams.put("orgId", orgId);
                    achievementParams.put("gradeId", gradeId);
                    achievementParams.put("termId", termId);
                    achievementParams.put("userId", achievementDto.getUserId());
                    achievementParams.put("type", achievementProjectDto.getType());
                    achievementParams.put("projectId", achievementProjectDto.getId());

                    //设置成绩
                    HlifeAchievement hlifeAchievement = hlifeAchievementMapper.getByMapParams(achievementParams);
                    if(null!=hlifeAchievement)
                    {
                        projectItemDto.setAchievement(hlifeAchievement.getAchievement());
                    }
                    else
                    {
                        projectItemDto.setAchievement("/");
                    }

                    achievementList.add(projectItemDto);
                }
                achievementDto.setAchievementList(achievementList);
            }
        }
        return pageInfo;
    }

    /**
     * 查询成绩
     * */
    @Override
    public AchievementDto getAchievement(Integer type,Long orgId,Long termId,Long userId)
    {
        AchievementDto achievementDto = new AchievementDto();
        achievementDto.setOrgId(orgId);
        achievementDto.setTermId(termId);
        achievementDto.setUserId(userId);

        //查询成绩上传记录
        List<AchievementProjectItemDto> achievementList = new ArrayList<>();

        Map<String, Object> recordParams = new HashMap<String, Object>();
        recordParams.put("orgId", orgId);
        recordParams.put("termId", termId);
        recordParams.put("userId", userId);
        List<HlifeAchievementRecord> recordList = hlifeAchievementRecordMapper.getListByMapParams(recordParams);
        for(HlifeAchievementRecord achievementRecord : recordList)
        {
            AchievementProjectItemDto projectItemDto = new AchievementProjectItemDto();
            projectItemDto.setType(achievementRecord.getType().intValue());
            projectItemDto.setProjectId(achievementRecord.getProjectId());
            projectItemDto.setProjectName(achievementRecord.getProjectName());
            projectItemDto.setAchievement(achievementRecord.getAchievement());

            achievementList.add(projectItemDto);
        }

        achievementDto.setAchievementList(achievementList);

        return achievementDto;
    }

    /**
     * 修改成绩
     * */
    @Transactional
    @Override
    public void updateAchievement(AchievementDto achievementDto)
    {
        Long orgId = achievementDto.getOrgId();
        Long termId = achievementDto.getTermId();
        Long userId = achievementDto.getUserId();

        List<HlifeAchievement> achievementList = new ArrayList<>();
        List<HlifeAchievementRecord> achievementRecordList = new ArrayList<>();
        List<AchievementProjectItemDto> projectItemList = achievementDto.getAchievementList();
        for(AchievementProjectItemDto projectItemDto : projectItemList)
        {
            Map<String,Object> achievementParams = new HashMap<String, Object>();
            achievementParams.put("orgId", orgId);
            achievementParams.put("termId", termId);
            achievementParams.put("userId", userId);
            achievementParams.put("type", projectItemDto.getType());
            achievementParams.put("projectId", projectItemDto.getProjectId());

            HlifeAchievement hlifeAchievement = hlifeAchievementMapper.getByMapParams(achievementParams);
            if(null!=hlifeAchievement)
            {
                achievementList.add(hlifeAchievement);
            }
        }

        //批量修改
        hlifeAchievementMapper.updateBatch(achievementList);
    }

    /**
     * 下载成绩模板
     * */
    @Override
    public AchievementExcelDto downloadAchievementTmeplateExcel(Integer type, Long orgId, Long termId, Long gradeId, Long classId, Integer sex)
    {

        AchievementExcelDto achievementExcelPageDto = new AchievementExcelDto();

        //查询项目
        List<AchievementProjectDto> projectList = this.getProjectList(orgId,termId,gradeId,sex);

        //组装表头
        List<String> headerList = getExcelTemplateHeader(projectList);
        achievementExcelPageDto.setHeaderList(headerList);

        //查询学生列表
        List<AchievementDto> studentList = new ArrayList<>();
        ResultDTO<List<StudentInfoDto>> studentResult = null;
        if(null==classId)
        {
            studentResult = basicFeignService.getGradeStudentList(orgId, gradeId, this.getSexName(sex));
        }
        else
        {
            studentResult = basicFeignService.getStudentInfoListByClassId(orgId, classId);
        }

        if(studentResult.isSuccess() && null!=studentResult.getData())
        {
            List<StudentInfoDto> studentInfoDtoList = studentResult.getData();
            for(StudentInfoDto studentInfoDto : studentInfoDtoList)
            {
                //按班级查询时过滤性别
                if(null!=classId&&null!=sex&&sex!=0)
                {
                    if(!this.getSexType(studentInfoDto.getSex()).equals(sex))
                    {
                        continue;
                    }
                }

                AchievementDto achievementDto = new AchievementDto();
                achievementDto.setOrgId(studentInfoDto.getOrgId());
                achievementDto.setGradeId(studentInfoDto.getGradeId());
                achievementDto.setGradeName(studentInfoDto.getGradeName());
                achievementDto.setClassId(studentInfoDto.getClassId());
                achievementDto.setClassName(studentInfoDto.getClassName());
                achievementDto.setUserId(studentInfoDto.getUserId());
                achievementDto.setUserName(studentInfoDto.getName());
                achievementDto.setStrSex(studentInfoDto.getSex());
                achievementDto.setUserNo(studentInfoDto.getStudentNo());

                //根据项目查询学生成绩
                List<AchievementProjectItemDto> achievementList = new ArrayList<>();
                for(AchievementProjectDto achievementProjectDto : projectList)
                {

                    if(SportsExamineTypeEnum.BMI.getDesc().equals(achievementProjectDto.getName().trim()))
                    {
                        //身高
                        AchievementProjectItemDto heightItem = new AchievementProjectItemDto();
                        heightItem.setAchievement("");
                        achievementList.add(heightItem);

                        //体重
                        AchievementProjectItemDto weightItem = new AchievementProjectItemDto();
                        weightItem.setAchievement("");
                        achievementList.add(weightItem);
                    }
                    else if(SportsExamineTypeEnum.SIGHT.getDesc().equals(achievementProjectDto.getName().trim()))
                    {
                        //左视力
                        AchievementProjectItemDto leftSigntItem = new AchievementProjectItemDto();
                        leftSigntItem.setAchievement("");
                        achievementList.add(leftSigntItem);

                        //右视力
                        AchievementProjectItemDto rightSigntItem = new AchievementProjectItemDto();
                        rightSigntItem.setAchievement("");
                        achievementList.add(rightSigntItem);
                    }
                    else {
                        AchievementProjectItemDto projectItemDto = new AchievementProjectItemDto();
                        projectItemDto.setAchievement("");
                        achievementList.add(projectItemDto);
                    }
                }

                achievementDto.setAchievementList(achievementList);

                studentList.add(achievementDto);
            }
        }

        achievementExcelPageDto.setDataList(studentList);

        return achievementExcelPageDto;
    }

    /**
     * 下载成绩
     * */
    @Override
    public AchievementExcelDto downloadAchievementExcel(Integer type, Long orgId, Long termId, Long gradeId, Long classId, Integer sex)
    {

        AchievementExcelDto achievementExcelPageDto = new AchievementExcelDto();

        //查询考试信息
        HlifeTerm hlifeTerm = hlifeTermMapper.getByPrimaryKey(termId);
        TermDto termDto = new TermDto();
        if(null!=hlifeTerm) {
            BeanUtils.copyProperties(hlifeTerm, termDto);
            achievementExcelPageDto.setTerm(termDto);
        }

        //查询项目
        List<AchievementProjectDto> projectList = this.getProjectList(orgId,termId,gradeId,sex);

        //组装表头
        List<String> headerList = this.getAchievementExcelHeader(projectList);
        achievementExcelPageDto.setHeaderList(headerList);

        //组装成绩数据
        PageInfo<AchievementDto> pageInfo = this.getAchievementPageInfo(orgId, termId, gradeId, classId, sex, 1, 10000, projectList);
        achievementExcelPageDto.setDataList(pageInfo.getList());

        return achievementExcelPageDto;
    }

    /**
     * 获取体测项目
     * */
    private List<AchievementProjectDto> getProjectList(Long orgId,Long termId,Long gradeId,Integer sex)
    {
        Map<String, Object> projectParams = new HashMap<String, Object>();
        projectParams.put("orgId", orgId);
        projectParams.put("gradeId", gradeId);
        if(null!=sex && sex!=0)
        {
            projectParams.put("sex", sex);
        }

        List<AchievementProjectDto> projectList = new ArrayList<>();
        List<AchievementProjectDto> projectDtoList = hlifeAchievementMapper.getAchievementProjectList(projectParams);
        HlifeTerm hlifeTerm = hlifeTermMapper.getByPrimaryKey(termId);
        if(null!=hlifeTerm)
        {
            JSONObject jsonObject = JSONObject.parseObject(hlifeTerm.getProjectInfo().toString());

            //过滤体检项目
            String examineStr = jsonObject.getString("examine");
            if(!StringUtils.isEmpty(examineStr)) {
                JSONArray examineArr = JSON.parseArray(examineStr);
                for(int i=0;i<examineArr.size();i++)
                {
                    JSONObject examineJson = JSONObject.parseObject(JSON.toJSONString(examineArr.get(i)));
                    Long projectId = examineJson.getLong("id");
                    String projectName = examineJson.getString("name");
                    for(AchievementProjectDto projectDto : projectDtoList) {
                        if(projectDto.getType().equals(SportsProjectTypeEnum.EXAMINE.getValue().intValue()) && projectDto.getId().equals(projectId)) {
                            AchievementProjectDto achievementProjectDto = new AchievementProjectDto();
                            achievementProjectDto.setId(projectId);
                            achievementProjectDto.setName(projectName);
                            achievementProjectDto.setType(SportsProjectTypeEnum.EXAMINE.getValue().intValue());
                            projectList.add(achievementProjectDto);
                        }
                    }
                }
            }

            //过滤体质项目
            String physicalStr = jsonObject.getString("physical");
            if(!StringUtils.isEmpty(physicalStr)) {
                JSONArray physicalArr = JSON.parseArray(physicalStr);
                for(int i=0;i<physicalArr.size();i++)
                {
                    JSONObject physicalJson = JSONObject.parseObject(JSON.toJSONString(physicalArr.get(i)));
                    Long projectId = physicalJson.getLong("id");
                    String projectName = physicalJson.getString("name");
                    for(AchievementProjectDto projectDto : projectDtoList) {
                        if(projectDto.getType().equals(SportsProjectTypeEnum.PHYSICAL.getValue().intValue()) && projectDto.getId().equals(projectId)) {
                            AchievementProjectDto achievementProjectDto = new AchievementProjectDto();
                            achievementProjectDto.setId(projectId);
                            achievementProjectDto.setName(projectName);
                            achievementProjectDto.setType(SportsProjectTypeEnum.PHYSICAL.getValue().intValue());
                            projectList.add(achievementProjectDto);
                        }
                    }
                }
            }
        }

        return projectList;
    }

    private List<AchievementProjectItemDto> getAchievementHeader(List<AchievementProjectDto> projectList)
    {
        List<AchievementProjectItemDto> headerList = new ArrayList<>();

        AchievementProjectItemDto name = new AchievementProjectItemDto();
        name.setProjectName("姓名");
        headerList.add(name);

        AchievementProjectItemDto sex = new AchievementProjectItemDto();
        sex.setProjectName("性别");
        headerList.add(sex);

        for(AchievementProjectDto projectDto : projectList)
        {
            AchievementProjectItemDto project = new AchievementProjectItemDto();
            project.setType(projectDto.getType());
            project.setProjectId(projectDto.getId());
            project.setProjectName(projectDto.getName());
            headerList.add(project);
        }

        return headerList;
    }

    private List<String> getExcelTemplateHeader(List<AchievementProjectDto> projectList)
    {
        List<String> headerList = new ArrayList<>();

        headerList.add("年级");
        headerList.add("班级");
        headerList.add("姓名");
        headerList.add("性别");
        headerList.add("学籍号");

        for(AchievementProjectDto projectDto : projectList)
        {
            if(SportsExamineTypeEnum.BMI.getDesc().equals(projectDto.getName().trim()))
            {
                headerList.add("身高");
                headerList.add("体重");
            }
            else if(SportsExamineTypeEnum.SIGHT.getDesc().equals(projectDto.getName().trim()))
            {
                headerList.add("左眼裸眼视力");
                headerList.add("右眼裸眼视力");
            }
            else {
                headerList.add(projectDto.getName());
            }
        }

        return headerList;
    }

    private List<String> getAchievementExcelHeader(List<AchievementProjectDto> projectList)
    {
        List<String> headerList = new ArrayList<>();

        headerList.add("年级");
        headerList.add("班级");
        headerList.add("姓名");
        headerList.add("性别");
        headerList.add("学籍号");

        for(AchievementProjectDto projectDto : projectList)
        {
            headerList.add(projectDto.getName());
        }

        return headerList;
    }

    /**
     * 上传成绩
     * */
    @Override
    public void uploadAchievement(BasicFeignService basicFeignService, Integer type, Long orgId, Long termId, List<Object[]> titleList, List<Object[]> dataList, Integer currentRow)
    {
        Object[] projectObject = titleList.get(0);
        for (Object[] data : dataList) {
            try {
                String gradeName = data[0].toString();//年级名称
                String className = data[1].toString();//班级名称
                String studentName = data[2].toString();//姓名
                String studentNo = data[4].toString();//学号
                String strHeight = data[5].toString();//身高
                String strWeight = data[6].toString();//体重
                String strLeftSight = data[7].toString();//左眼视力
                String strRightSight = data[8].toString();//右眼视力
                String heightTitle = (String) projectObject[5];
                String weightTitle = (String) projectObject[6];
                String leftSightTitle = (String) projectObject[7];
                String rightSightTitle = (String) projectObject[8];
                if (strHeight.endsWith(".0")) {
                    strHeight = strHeight.substring(0, strHeight.indexOf(".0"));
                }
                if (strWeight.endsWith(".0")) {
                    strWeight = strWeight.substring(0, strWeight.indexOf(".0"));
                }
                log.info("gradeName:{} className:{} studentName:{} studentNo:{} height:{} weight:{} strLeftSight:{} strRightSight:{}", gradeName, className, studentName, studentNo, strHeight, strWeight, strLeftSight, strRightSight);

                GradeDto gradeDto = null;
                ResultDTO<GradeDto> gradeResultDTO = basicFeignService.getGradeByName(orgId, gradeName);
                if (gradeResultDTO.isSuccess() && null != gradeResultDTO.getData()) {
                    gradeDto = gradeResultDTO.getData();
                }
                else
                {
                    continue;
                }

                ClassInfoDto classInfoDto = null;
                StudentInfoDto studentInfoDto = null;
                ResultDTO<ClassInfoDto> classResultDTO = basicFeignService.getClassByName(orgId, gradeDto.getId(), className);
                if (classResultDTO.isSuccess() && null != classResultDTO.getData()) {
                    classInfoDto = classResultDTO.getData();
                }

                ResultDTO<StudentInfoDto> studentResultDTO = basicFeignService.getStudentByStudentNo(orgId,null,null, studentNo);
                if (studentResultDTO.isSuccess() && null != studentResultDTO.getData()) {
                    studentInfoDto = studentResultDTO.getData();
                }

                log.info("classInfoDto:{} studentInfoDto:{}", classInfoDto, studentInfoDto);
                if (null == classInfoDto || null == studentInfoDto) {
                    log.info("班级或用户不存在 className:{} studentNo:{}", className, studentNo);
                    continue;
                }

                //保存BMI数据
                this.saveBmi(orgId, termId, classInfoDto, studentInfoDto, heightTitle, strHeight, weightTitle, strWeight);

                //保存视力数据
                this.saveSight(orgId, termId, classInfoDto, studentInfoDto, leftSightTitle, strLeftSight, rightSightTitle, strRightSight);

                //组装数据
                for (int i = 0; i < data.length; i++) {
                    if (i > 8) {

                        String projectName = (String) projectObject[i];
                        String score = data[i].toString();
                        if (score.endsWith(".0")) {
                            score = score.substring(0, score.indexOf(".0"));
                        }
                        log.info("projectName:{} score:{}", projectName, score);

                        //分数不为空才保存
                        if (!StringUtils.isEmpty(score)) {
                            this.saveAchievement(orgId, termId, classInfoDto, studentInfoDto, projectName, score);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                log.info("上传成绩第{}行数据异常",currentRow,e);
            }
        }
    }

    /**
     * 按学期计算学生成绩
     * */
    @Override
    public void doTermAchievementScore(Long orgId, Long termId)
    {
        AchievementProjectRuleDto projectRuleDto = this.getProjectRule();
        
        HashMap<String, Object> params = new HashMap<>();

        params.put("orgId", orgId);
        params.put("termId", termId);
        
        List<HlifeAchievement> achievements = hlifeAchievementMapper.getListByMapParams(params);
        
        List<HlifeAchievement> achievementList = new ArrayList<>();
        
        for(HlifeAchievement achievement : achievements) {
        	if(calculateProjectScore(projectRuleDto, achievement)) {
        		achievementList.add(achievement);
        	}
        }
        
        List<HlifeAchievementStat> stats = calculateUserScore(achievementList);

        batchModify(achievementList, stats);
    }

	/**
     * 按学生计算成绩统计
     * */
    @Override
    public void doUserAchievementScore(AchievementProjectRuleDto projectRuleDto, Long orgId, Long termId, Long userId)
    {
        
        HashMap<String, Object> params = new HashMap<>();

        params.put("orgId", orgId);
        params.put("termId", termId);
        params.put("userId", userId);
        
    	List<HlifeAchievement> achievements = hlifeAchievementMapper.getListByMapParams(params);
    	
    	List<HlifeAchievement> achievementList = new ArrayList<>();
    	for(HlifeAchievement achievement : achievements) {
    		if(calculateProjectScore(projectRuleDto, achievement)) {
    			achievementList.add(achievement);
    		}
    	}
    	
    	List<HlifeAchievementStat> stats = calculateUserScore(achievementList);
    	
    	batchModify(achievementList, stats);
    }

	private void batchModify(List<HlifeAchievement> achievementList, List<HlifeAchievementStat> stats) {
		
		Date dt = new Date();
		
		for(HlifeAchievement achievement : achievementList) {
        	achievement.setUpdateTime(dt);
    		hlifeAchievementMapper.updateScore(achievement);
    	}
        
    	for(HlifeAchievementStat stat : stats) {
    		if(hlifeAchievementStatMapper.exist(stat) > 0) {
    			stat.setUpdateTime(dt);
    			hlifeAchievementStatMapper.updateScore(stat);
    		}else {
    			stat.setCreateTime(dt);
    			stat.setUpdateTime(dt);
    			hlifeAchievementStatMapper.insert(stat);
    		}
    	}
	}
    
    
    private List<HlifeAchievementStat> calculateUserScore(List<HlifeAchievement> achievementList) {
    	
    	TreeMap<HlifeAchievementStat, HlifeAchievementStat> stats = new TreeMap<>(new Comparator<HlifeAchievementStat>() {

			@Override
			public int compare(HlifeAchievementStat stat1, HlifeAchievementStat stat2) {
				long reval = stat1.getOrgId() - stat2.getOrgId();
				if(reval != 0) {
					return reval > 0 ? 1 : -1;
				}
				reval = stat1.getGradeId() - stat2.getGradeId();
				if(reval != 0) {
					return reval > 0 ? 1 : -1;
				}
				reval = stat1.getClassId() - stat2.getClassId();
				if(reval != 0) {
					return reval > 0 ? 1 : -1;
				}
				reval = stat1.getTermId() - stat2.getTermId();
				if(reval != 0) {
					return reval > 0 ? 1 : -1;
				}
				reval = stat1.getUserId() - stat2.getUserId();
				if(reval != 0) {
					return reval > 0 ? 1 : -1;
				}
				return 0;
			}
        	
        });
    	

        
        for(HlifeAchievement achievement : achievementList) {
        	
        	HlifeAchievementStat stat = new HlifeAchievementStat();
        	stat.setOrgId(achievement.getOrgId());
        	stat.setGradeId(achievement.getGradeId());
        	stat.setClassId(achievement.getClassId());
        	stat.setTermId(achievement.getTermId());
        	stat.setUserId(achievement.getUserId());
        	
        	if(stats.containsKey(stat)) {
        		stat = stats.get(stat);
        	}else {
        		stat.setScore(0D);
        		stat.setTotalScore(0D);
        		stat.setPluses(0D);
        		stats.put(stat, stat);
        	}
        	double score = stat.getScore() + achievement.getWeightScore();
        	stat.setScore(score);
        	double pluses = stat.getPluses() + achievement.getPlusesScore();
        	stat.setPluses(pluses);
        	double totalScore = stat.getTotalScore() + achievement.getWeightScore() + achievement.getPlusesScore();
        	stat.setTotalScore(totalScore);
        }
        
        List<HlifeAchievementStat> list = new ArrayList<>(stats.values());
        
        for(HlifeAchievementStat stat : list) {
        	logout("user:" + stat.getUserId() + ", score:" + stat.getScore() + ", total:" + stat.getTotalScore());
        }
        
        return list;
    }

    private boolean calculateProjectScore(AchievementProjectRuleDto projectRules, HlifeAchievement achievement) {
    	
    	boolean reval = false;
    	/*
    	achievement.setScore(0D);
    	achievement.setWeightScore(0D);
    	achievement.setPlusesScore(0D);*/
    	
    	String tp = "physical";
    	
    	int type = achievement.getType();
    	
    	if(type == 1) {
    		tp = "exam";
    	}
    	
    	logout("user:" + achievement.getUserId() + ", sex:" + achievement.getSex()
    				   + ", org:" + achievement.getOrgId()   + ", grade:" + achievement.getGradeId()
    				   + ", type:" + tp  + ", project:" + achievement.getProjectId()  + ", achievement:" + achievement.getAchievement());
    	
    	if(type == 2) {
    		
    		List<PhysicalDto> physicals = projectRules.getPhysicalList();
    		achievement.setGradeId(achievement.getRuleGradeId());
    		achievement.setOrgId(1L);
    		reval = calculatePhysicalScore(achievement, physicals);
    		
    	}else if(type == 1) {
    		
    		List<ExamineDto> exams = projectRules.getExamineList();
    		reval = calculateExamScore(achievement, exams);
    	}
    	
    	if(reval) {
    		logout(" matched success, score:" + achievement.getScore() 
    			+ ", weightScore:" + achievement.getWeightScore() 
    			+ ", plusesScore:" + achievement.getPlusesScore());
    	}else {
    		logout(" matched fail");
    	}
    	logout("");
    	
    	return reval;
	}

	private boolean calculatePhysicalScore(HlifeAchievement achievement, List<PhysicalDto> physicals) {
		double ach;
		boolean reval = false;
		for(PhysicalDto physical : physicals) {
			if(compareValue(physical.getOrgId(), achievement.getOrgId()) 
				&& compareValue(physical.getId(), achievement.getProjectId())) {
				logout(" matched(physical:" + physical.getId() + ", org:" + physical.getOrgId() + ")");
				try{
					ach = SportsUtils.translate(physical.getUnit(), achievement.getAchievement());
				}catch(Throwable e) {
					continue;
				}
				List<PhysicalRuleDto> rules = physical.getRuleList();
				if(rules == null) {
					continue;
				}
				for(PhysicalRuleDto rule : rules) {
					if(compareValue(rule.getGradeId(), achievement.getGradeId()) 
						&& (rule.getSex() == 0 || compareValue(rule.getSex(), achievement.getSex()))) {
						logout(" matched(rule:" + rule.getId() + ", grade:" + rule.getGradeId() + ", sex:" + rule.getSex() + ", ruleType:" + rule.getRuleType() + ") weight:" + rule.getWeight());
						double weight = rule.getWeight();
						List<PhysicalRuleItemDto> items = rule.getItemDtoList();
						if(items == null) {
							continue;
						}
						for(PhysicalRuleItemDto item : items) {
							if(matchScope("item:" + item.getId(), ach, rule.getRuleType(), item.getMin(), item.getMax())) {
								achievement.setScore(item.getScore());
								double weightScore = weight * item.getScore() / 100;
								achievement.setWeightScore(weightScore);
								reval = true;
								break;
							}
						}
						List<PhysicalRulePlusesDto> pluses = rule.getPlusesList();
						if(pluses == null) {
							continue;
						}
						for(PhysicalRulePlusesDto plus : pluses) {
							if(matchScope("plus:" + plus.getId(), ach, rule.getRuleType(), plus.getMin(), plus.getMax())) {
								achievement.setPlusesScore(plus.getScore());
								reval = true;
								break;
							}
						}
					}
				}
			}
		}
		return reval;
	}

	private boolean calculateExamScore(HlifeAchievement achievement, List<ExamineDto> exams) {
		double ach;
		boolean reval = false;
		for(ExamineDto exam : exams) {
			if(compareValue(exam.getOrgId(), achievement.getOrgId()) 
				&& compareValue(exam.getId(), achievement.getProjectId())) {
				logout(" matched(exam:" + exam.getId() + ", org:" + exam.getOrgId() + ")");
				try{
					ach = SportsUtils.translate(exam.getUnit(), achievement.getAchievement());
				}catch(Throwable e) {
					continue;
				}
				List<ExamineRuleDto> rules = exam.getRuleList();
				if(rules == null) {
					continue;
				}
				for(ExamineRuleDto rule : rules) {
					if(compareValue(rule.getGradeId(), achievement.getGradeId()) 
						&& (rule.getSex() == 0 || compareValue(rule.getSex(), achievement.getSex()))) {
						logout(" matched(rule:" + rule.getId() + ", grade:" + rule.getGradeId() + ", sex:" + rule.getSex() + ", ruleType:" + rule.getRuleType() + ") weight:" + rule.getWeight());
						double weight = rule.getWeight();
						List<ExamineRuleItemDto> items = rule.getRuleItemList();
						if(items == null) {
							continue;
						}
						for(ExamineRuleItemDto item : items) {
							//logout("item:" + item);
							if(matchScope("item:" + item.getId(), ach, rule.getRuleType(), item.getMin(), item.getMax())) {
								achievement.setScore(item.getScore());
								double weightScore = weight * item.getScore() / 100;
								achievement.setWeightScore(weightScore);
								reval = true;
								break;
							}
						}
						List<ExamineRulePlusesDto> pluses = rule.getPlusesList();
						if(pluses == null) {
							continue;
						}
						for(ExamineRulePlusesDto plus : pluses) {
							if(matchScope("plus:" + plus.getId(), ach, rule.getRuleType(), plus.getMin(), plus.getMax())) {
								achievement.setPlusesScore(plus.getScore());
								reval = true;
								break;
							}
						}
					}
				}
			}
		}
		return reval;
	}
	
	
	private boolean matchScope(String prefix, double value, int type, double min, double max) {
		boolean reval;
		String msg;
		if(type == 2) {
			reval = value >= min && value < max;
			msg = " matched(" + prefix + ", " + min + " <= " + value + " < " + max + ")";
		}else {
			reval = value > min && value <= max;
			msg =" matched(" + prefix + ", " + min + " < " + value + " <= " + max + ")";
		}
		if(reval) {
			logout(msg);
		}
		return reval;
	}
    
    private void logout(String msg) {
    	//System.out.println(msg);
    	log.info(msg);
    }

	/**
     * 获取项目计算规则
     * */
    private AchievementProjectRuleDto getProjectRule()
    {
        AchievementProjectRuleDto projectRuleDto = new AchievementProjectRuleDto();
        
        List<ExamineDto> examineList = hlifeExamineMapper.getExamineList();
        
        List<ExamineRuleDto> examineRuleList = hlifeExamineRuleMapper.getExamineRuleList();
        
        List<ExamineRuleItemDto> examineRuleItemList = hlifeExamineRuleItemMapper.getExamineRuleItemList();
        
        List<ExamineRulePlusesDto> examineRulePlusList = hlifeExamineRulePlusesMapper.getExamineRulePlusList();
        
        for(ExamineRuleDto rule : examineRuleList) {
        	for(ExamineDto exam : examineList) {
        		if(compareValue(exam.getId(), rule.getExaminationId())) {
        			List<ExamineRuleDto> list = exam.getRuleList();
        			if(list == null) {
        				list = new ArrayList<>();
        				exam.setRuleList(list);
        			}
            		list.add(rule);
        		}
        	}
        }
        
        for(ExamineRuleItemDto item : examineRuleItemList) {
        	for(ExamineRuleDto rule : examineRuleList) {
        		if(compareValue(rule.getId(), item.getRuleId())) {
        			List<ExamineRuleItemDto> list = rule.getRuleItemList();
        			if(list == null) {
        				list = new ArrayList<>();
        				rule.setRuleItemList(list);
        			}
            		list.add(item);
        		}
        	}
        }
        
        for(ExamineRulePlusesDto plus : examineRulePlusList) {
        	for(ExamineRuleDto rule : examineRuleList) {
        		if(compareValue(rule.getId(), plus.getRuleId())) {
        			List<ExamineRulePlusesDto> list = rule.getPlusesList();
        			if(list == null) {
        				list = new ArrayList<>();
        				rule.setPlusesList(list);
        			}
            		list.add(plus);
        		}
        	}
        }
        
        List<PhysicalDto> physicalList = hlifePhysicalMapper.getPhysicalList();
        
        List<PhysicalRuleDto> physicalRuleList = hlifePhysicalRuleMapper.getPhysicalRuleList();
        
        List<PhysicalRuleItemDto> physicalRuleItemList = hlifePhysicalRuleItemMapper.getPhysicalRuleItemList();
        
        List<PhysicalRulePlusesDto> physicalRulePlusList = hlifePhysicalRulePlusesMapper.getPhysicalRulePlusList();
        
        for(PhysicalRuleDto rule : physicalRuleList) {
        	for(PhysicalDto physical : physicalList) {
        		if(compareValue(physical.getId(), rule.getPhysicalId())) {
        			List<PhysicalRuleDto> list = physical.getRuleList();
        			if(list == null) {
        				list = new ArrayList<>();
        				physical.setRuleList(list);
        			}
            		list.add(rule);
        		}
        	}
        }
        
        for(PhysicalRuleItemDto item : physicalRuleItemList) {
        	for(PhysicalRuleDto rule : physicalRuleList) {
        		if(compareValue(rule.getId(), item.getRuleId())) {
        			List<PhysicalRuleItemDto> list = rule.getItemDtoList();
        			if(list == null) {
        				list = new ArrayList<>();
        				rule.setItemDtoList(list);
        			}
            		list.add(item);
        		}
        	}
        }
        
        for(PhysicalRulePlusesDto plus : physicalRulePlusList) {
        	for(PhysicalRuleDto rule : physicalRuleList) {
        		if(compareValue(rule.getId(), plus.getRuleId())) {
        			List<PhysicalRulePlusesDto> list = rule.getPlusesList();
        			if(list == null) {
        				list = new ArrayList<>();
        				rule.setPlusesList(list);
        			}
            		list.add(plus);
        		}
        	}
        }
        
        projectRuleDto.setExamineList(examineList);
        projectRuleDto.setPhysicalList(physicalList);
        
        printRule(projectRuleDto);

        return projectRuleDto;
    }
    
    private boolean compareValue(Number n1, Number n2) {
    	if(n1 == null || n2 == null) {
    		return false;
    	}
    	if(n1 instanceof Long) {
    		return n1.longValue() == n2.longValue();
    	}
    	if(n1 instanceof Byte) {
    		return n1.byteValue() == n2.byteValue();
    	}
    	return n1.intValue() == n2.intValue();
    }

	private void printRule(AchievementProjectRuleDto projectRuleDto) {
		List<ExamineDto> examineList = projectRuleDto.getExamineList();
		List<PhysicalDto> physicalList = projectRuleDto.getPhysicalList();
		for(PhysicalDto physical : physicalList) {
        	logout("physical org:" + physical.getOrgId() + ", id:" + physical.getId() + ", name:" + physical.getName() + ", unit:" + physical.getUnit());
        	if(physical.getRuleList() == null) {
        		continue;
        	}
        	for(PhysicalRuleDto rule : physical.getRuleList()) {
        		logout("   name:" + rule.getGradeName() + ", id:" + rule.getId() + ", grade:" + rule.getGradeId() + ", sex:" + rule.getSex() + ", weight:" + rule.getWeight());
        		if(rule.getItemDtoList() == null) {
        			continue;
        		}
        		for(PhysicalRuleItemDto item : rule.getItemDtoList()) {
        			logout("      score:" + item.getScore() + " when " + item.getMax() + "> n >=" + item.getMin());
    			}
        		if(rule.getPlusesList() == null) {
        			continue;
        		}
        		for(PhysicalRulePlusesDto plus : rule.getPlusesList()) {
        			logout("      plusScore:" + plus.getScore() + " when " + plus.getMax() + "> n >=" + plus.getMin());
    			}
        	}
        	logout("");
        }
        
        for(ExamineDto exam : examineList) {
        	logout("exam org:" + exam.getOrgId() + ", id:" + exam.getId() + ", name:" + exam.getName() + ", unit:" + exam.getUnit());
        	if(exam.getRuleList() == null) {
        		continue;
        	}
        	for(ExamineRuleDto rule : exam.getRuleList()) {
        		logout("   name:" + rule.getGradeName() + ", id:" + rule.getId() + ", grade:" + rule.getGradeId() + ", sex:" + rule.getSex() + ", weight:" + rule.getWeight());
        		if(rule.getRuleItemList() == null) {
        			continue;
        		}
        		for(ExamineRuleItemDto item : rule.getRuleItemList()) {
        			logout("      score:" + item.getScore() + " when " + item.getMax() + "> n >=" + item.getMin());
    			}
        		if(rule.getPlusesList() == null) {
        			continue;
        		}
        		for(ExamineRulePlusesDto plus : rule.getPlusesList()) {
        			logout("      plusScore:" + plus.getScore() + " when " + plus.getMax() + "> n >=" + plus.getMin());
    			}
        	}
        	logout("");
        }
	}

    private void saveSight(Long orgId, Long termId, ClassInfoDto classInfoDto, StudentInfoDto studentInfoDto, String leftSightTitle, String strLeftSight, String rightSightTitle, String strRightSight) {
        String strSight = null;
        Double sight = 0d;
        if(!StringUtils.isEmpty(strLeftSight)&&!StringUtils.isEmpty(strRightSight)) {
            double leftSight = Double.parseDouble(strLeftSight);
            double rightSight = Double.parseDouble(strRightSight);
            if(leftSight<rightSight)
            {
                sight = leftSight;
            }
            else
            {
                sight = rightSight;
            }
        }
        else {
            if (!StringUtils.isEmpty(strLeftSight)&&StringUtils.isEmpty(strRightSight))
            {
                sight = Double.parseDouble(strLeftSight);
            }
            else if (StringUtils.isEmpty(strLeftSight)&&!StringUtils.isEmpty(strRightSight))
            {
                sight = Double.parseDouble(strRightSight);
            }
        }

        String projectName = SportsExamineTypeEnum.SIGHT.getDesc();
        this.saveAchievement(orgId, termId, classInfoDto, studentInfoDto, projectName, ""+sight);
        this.saveAchievementRecord(orgId, termId, classInfoDto, studentInfoDto, SportsProjectTypeEnum.EXAMINE.getValue(), null,leftSightTitle, strLeftSight);
        this.saveAchievementRecord(orgId, termId, classInfoDto, studentInfoDto, SportsProjectTypeEnum.EXAMINE.getValue(), null,rightSightTitle, leftSightTitle);
    }

    private void saveBmi(Long orgId, Long termId, ClassInfoDto classInfoDto, StudentInfoDto studentInfoDto, String heightTitle, String strHeight, String weightTitle,String strWeight) {
        if(!StringUtils.isEmpty(strHeight)&&!StringUtils.isEmpty(strWeight)) {
            float height = Float.parseFloat(strHeight)/100;
            float weight = Float.parseFloat(strWeight);
            double bmi = weight / (height * height);
            BigDecimal bg = new BigDecimal(bmi).setScale(2, RoundingMode.UP);
            bmi = bg.doubleValue();

            String projectName = SportsExamineTypeEnum.BMI.getDesc();
            this.saveAchievement(orgId, termId, classInfoDto, studentInfoDto, projectName, ""+bmi);
            this.saveAchievementRecord(orgId, termId, classInfoDto, studentInfoDto, SportsProjectTypeEnum.EXAMINE.getValue(), null,heightTitle, strHeight);
            this.saveAchievementRecord(orgId, termId, classInfoDto, studentInfoDto, SportsProjectTypeEnum.EXAMINE.getValue(), null,weightTitle, strWeight);
        }
    }

    /**
     * 保存成绩
     * */
    private void saveAchievement(Long orgId, Long termId, ClassInfoDto classInfoDto, StudentInfoDto studentInfoDto, String projectName, String achievement) {

        //替换中文分秒字符
        if(!StringUtils.isEmpty(achievement))
        {
            if(achievement.indexOf("’")>-1||achievement.indexOf("′")>-1)
            {
                achievement = achievement.replaceAll("’","'");
                achievement = achievement.replaceAll("′","'");
            }

            if(achievement.indexOf("“")>-1||achievement.indexOf("\"")>-1)
            {
                achievement = achievement.replaceAll("“","\"");
                achievement = achievement.replaceAll("\"","\"");
            }
        }

        HlifeAchievement hlifeAchievement = new HlifeAchievement();
        hlifeAchievement.setOrgId(orgId);
        hlifeAchievement.setGradeId(classInfoDto.getGradeId());
        hlifeAchievement.setClassId(classInfoDto.getId());
        hlifeAchievement.setTermId(termId);
        hlifeAchievement.setUserId(studentInfoDto.getUserId());
        hlifeAchievement.setAchievement(achievement);
        hlifeAchievement.setStatus(1);

        HlifeUser hlifeUser = new HlifeUser();
        hlifeUser.setUserType((byte) RoleTypeEnum.STUDENT.getValue());
        hlifeUser.setOrgId(orgId);
        hlifeUser.setGradeId(classInfoDto.getGradeId());
        hlifeUser.setGradeName(classInfoDto.getGradeName());
        hlifeUser.setClassId(classInfoDto.getId());
        hlifeUser.setClassName(classInfoDto.getClassName());
        hlifeUser.setUserId(studentInfoDto.getUserId());
        hlifeUser.setUserName(studentInfoDto.getName());
        hlifeUser.setSex(SexTypeEnum.getValue(studentInfoDto.getSex()).byteValue());
        hlifeUser.setHeadImg(studentInfoDto.getHeadImgUrl());
        hlifeUser.setMobile(studentInfoDto.getMobile());
        hlifeUser.setUserNo(studentInfoDto.getStudentNo());

        Integer achievementType = null;
        Long projectId = null;
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("orgId", orgId);
        params.put("name", projectName);
        HlifeExamine hlifeExamine = hlifeExamineMapper.getByMapParams(params);
        if (null != hlifeExamine) {
            achievementType = SportsProjectTypeEnum.EXAMINE.getValue();//体检
            projectId = hlifeExamine.getId();
        }
        else {
            params.put("orgId", 1);
            HlifePhysical hlifePhysical = hlifePhysicalMapper.getByMapParams(params);
            if (null != hlifePhysical) {
                achievementType = SportsProjectTypeEnum.PHYSICAL.getValue();//体检
                projectId = hlifePhysical.getId();
            }
        }

        if(null!=achievementType)
        {
            hlifeAchievement.setType(achievementType.byteValue());//体质
            hlifeAchievement.setProjectId(projectId);//项目ID

            Map<String, Object> achievementParams = new HashMap<String, Object>();
            achievementParams.put("orgId", orgId);
            achievementParams.put("termId", termId);
            achievementParams.put("userId", studentInfoDto.getUserId());
            achievementParams.put("type", achievementType);
            achievementParams.put("projectId", projectId);
            HlifeAchievement achievementObj = hlifeAchievementMapper.getByMapParams(achievementParams);
            if(null==achievementObj)
            {
                hlifeAchievementMapper.insert(hlifeAchievement);
            }
            else
            {
                hlifeAchievement.setId(achievementObj.getId());
                hlifeAchievementMapper.update(hlifeAchievement);
            }

            //保存用户信息
            Map<String, Object> userParams = new HashMap<String, Object>();
            userParams.put("orgId", orgId);
            userParams.put("userType", (byte)RoleTypeEnum.STUDENT.getValue());//用户类型(1教师 2家长 3学生)
            userParams.put("userId", studentInfoDto.getUserId());
            HlifeUser user = hlifeUserMapper.getByMapParams(userParams);
            if(null==user)
            {
                hlifeUserMapper.insert(hlifeUser);
            }
            else
            {
                hlifeUser.setId(user.getId());
                hlifeUserMapper.update(hlifeUser);
            }
        }

        this.saveAchievementRecord(orgId, termId, classInfoDto, studentInfoDto, achievementType, projectId, projectName, achievement);
    }

    /**
     * 保存上传数据记录
     * */
    private void saveAchievementRecord(Long orgId, Long termId, ClassInfoDto classInfoDto, StudentInfoDto studentInfoDto, Integer achievementType, Long projectId, String projectName, String achievement)
    {
        if(projectName.equals(SportsExamineTypeEnum.BMI.getDesc())||projectName.equals(SportsExamineTypeEnum.SIGHT.getDesc()))
        {
            return;
        }

        HlifeAchievementRecord achievementRecord = new HlifeAchievementRecord();
        achievementRecord.setOrgId(orgId);
        achievementRecord.setGradeId(classInfoDto.getGradeId());
        achievementRecord.setClassId(classInfoDto.getId());
        achievementRecord.setTermId(termId);
        achievementRecord.setUserId(studentInfoDto.getUserId());
        if(null!=achievementType) {
            achievementRecord.setType(achievementType.byteValue());
        }
        achievementRecord.setProjectId(projectId);
        achievementRecord.setProjectName(projectName);
        achievementRecord.setAchievement(achievement);

        Map<String, Object> recordParams = new HashMap<String, Object>();
        recordParams.put("orgId", orgId);
        recordParams.put("termId", termId);
        recordParams.put("userId", studentInfoDto.getUserId());
        recordParams.put("type", achievementType);
        recordParams.put("projectName", projectName);
        HlifeAchievementRecord record = hlifeAchievementRecordMapper.getByMapParams(recordParams);
        if(null==record)
        {
            hlifeAchievementRecordMapper.insert(achievementRecord);
        }
        else
        {
            achievementRecord.setId(record.getId());
            hlifeAchievementRecordMapper.update(achievementRecord);
        }
    }

    /**
     * 获取性别名称
     * */
    private String getSexName(Integer sex) {
        if(null!=sex)
        {
            if(1==sex)
            {
                return "男";
            }
            else if(2==sex)
            {
                return "女";
            }
        }
        return null;
    }

    /**
     * 获取性别
     * */
    private Integer getSexType(String sex) {
        if(!StringUtils.isEmpty(sex))
        {
            if("未知".equals(sex))
            {
                return 0;
            }
            if("男".equals(sex))
            {
                return 1;
            }
            else if("女".equals(sex))
            {
                return 2;
            }
        }
        return 0;
    }

}
